import 'dart:io';

import 'package:flutter_test/flutter_test.dart';
import 'package:saber/components/settings/update_manager.dart';
import 'package:saber/data/flavor_config.dart';
import 'package:saber/data/prefs.dart';
import 'package:saber/data/version.dart';
import 'package:shared_preferences/shared_preferences.dart';

/// Example current build number.
/// See [buildNumber] in [lib/data/version.dart].
const v = 5000;

void main() => group('Update manager:', () {
  FlavorConfig.setup();
  SharedPreferences.setMockInitialValues({});

  test('Test version comparison (release mode)', () {
    stows.shouldAlwaysAlertForUpdates.value = false;

    expect(UpdateManager.getUpdateStatus(v, v - 10), UpdateStatus.upToDate);
    expect(UpdateManager.getUpdateStatus(v, v - 1), UpdateStatus.upToDate);
    expect(UpdateManager.getUpdateStatus(v, v), UpdateStatus.upToDate);
    expect(UpdateManager.getUpdateStatus(v, v + 1), UpdateStatus.upToDate);
    expect(UpdateManager.getUpdateStatus(v, v + 9), UpdateStatus.upToDate);

    expect(
      UpdateManager.getUpdateStatus(v, v + 10),
      UpdateStatus.updateOptional,
    );
    expect(
      UpdateManager.getUpdateStatus(v, v + 11),
      UpdateStatus.updateOptional,
    );
    expect(
      UpdateManager.getUpdateStatus(v, v + 19),
      UpdateStatus.updateOptional,
    );

    expect(
      UpdateManager.getUpdateStatus(v, v + 20),
      UpdateStatus.updateRecommended,
    );
    expect(
      UpdateManager.getUpdateStatus(v, v + 100),
      UpdateStatus.updateRecommended,
    );
  });

  test('Test version comparison (debug mode)', () {
    stows.shouldAlwaysAlertForUpdates.value = true;

    expect(UpdateManager.getUpdateStatus(v, v), UpdateStatus.upToDate);
    expect(UpdateManager.getUpdateStatus(v, v + 1), UpdateStatus.upToDate);
    expect(UpdateManager.getUpdateStatus(v, v + 9), UpdateStatus.upToDate);
    expect(
      UpdateManager.getUpdateStatus(v, v + 10),
      UpdateStatus.updateRecommended,
    );
  });

  test(
    'Test that the latest version can be parsed from version.dart',
    () async {
      // load local file from lib/data/version.dart
      final latestVersionFile = await File(
        'lib/data/version.dart',
      ).readAsString();
      expect(
        latestVersionFile.isNotEmpty,
        true,
        reason: 'Failed to load local version.dart file',
      );

      final int? parsedVersion = await UpdateManager.getNewestVersion(
        latestVersionFile,
      );
      expect(
        parsedVersion,
        isNotNull,
        reason: 'Could not parse version number from version.dart file',
      );
      expect(
        parsedVersion,
        buildNumber,
        reason: 'Incorrect version number parsed from version.dart file',
      );
    },
  );

  test('Test that the latest version can be parsed from GitHub', () async {
    final int? newestVersion;
    try {
      newestVersion = await UpdateManager.getNewestVersion();
    } on SocketException {
      fail('Failed to download newest version from GitHub');
    }

    expect(
      newestVersion,
      isNotNull,
      reason: 'Could not parse version number from GitHub',
    );
    // at the time of writing, the latest version is 5050
    expect(
      newestVersion,
      greaterThan(5000),
      reason: 'Incorrect version number parsed from GitHub',
    );
  });
});
